package com.LearnInWorld.oauth.service.impl;

import com.LearnInWorld.oauth.service.OauthService;
import com.LearnInWorld.oauth.util.AuthToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.stereotype.Service;
import org.springframework.util.Base64Utils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.DefaultResponseErrorHandler;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Service
public class OauthServiceImpl implements OauthService {

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private LoadBalancerClient loadBalancerClient;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Value("${auth.ttl}")
    private Long ttl;

    /**
     *
     * @param username 用户名
     * @param password 密码
     * @param clientId 客户端id
     * @param clientSecret 客户端密码
     * @return
     */
    @Override
    public AuthToken login(String username, String password, String clientId, String clientSecret) {
        AuthToken authToken=new AuthToken();
        //获取访问路径
        ServiceInstance choose = loadBalancerClient.choose("LearnInWorld-user-oauth");
        URI uri = choose.getUri();
        String url = uri + "/oauth/token";
        //设置请求数据
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "password");
        body.add("username", username);
        body.add("password", password);
        //设置请求头
        MultiValueMap<String, String> handler = new LinkedMultiValueMap<>();
        handler.add("Authorization", this.httpBasic(clientId, clientSecret));
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(body, handler);
        restTemplate.setErrorHandler(new DefaultResponseErrorHandler() {
            @Override
            public void handleError(ClientHttpResponse response) throws IOException {
                if (response.getRawStatusCode() != 400 && response.getRawStatusCode() != 401) {
                    super.handleError(response);
                }
            }
        });
        //远程掉用获取token
        ResponseEntity<Map> exchange = restTemplate.exchange(url, HttpMethod.POST, requestEntity, Map.class);
        Map map = exchange.getBody();
        if (map==null||map.get("access_token")==null||map.get("refresh_token")==null||map.get("jti")==null){
            throw new RuntimeException("获取令牌失败");
        }
        authToken.setAccessToken((String)map.get("access_token"));
        authToken.setRefreshToken((String)map.get("refresh_token"));
        authToken.setJti((String)map.get("jti"));

        //将token数据存放到Redis中
        stringRedisTemplate.boundValueOps(authToken.getJti()).set(authToken.getAccessToken(),ttl, TimeUnit.SECONDS);

        return authToken;
    }

    private String httpBasic(String clientId, String clientPwd) {
        String string = clientId + ":" + clientPwd;
        byte[] encode = Base64Utils.encode(string.getBytes());
        return "Basic " + new String(encode);
    }
}
